﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace WPNextTools.NBase
{
    public class NControl : Control
    {
        #region Fields
        internal const char VisualStateDelimiter = ',';
        internal bool changePropertySilently;
        private bool isFocused;
        private bool isLoaded;
        private string currentVisualState;
        private bool isTemplateApplied;
        private byte visualStateUpdateLock;
        #endregion

        #region Properties
        public string CurrentVisualState
        {
            get
            {
                return this.currentVisualState;
            }
        }

        public bool IsLoaded
        {
            get
            {
                return this.isLoaded;
            }
        }

        public bool IsTemplateApplied
        {
            get
            {
                return this.isTemplateApplied;
            }
        }

        public bool IsFocused
        {
            get
            {
                return this.isFocused;
            }
            protected set
            {
                base.SetValue(IsFocusedProperty, value);
            }
        }

        protected internal virtual bool IsPropertyTemplated
        {
            get
            {
                return this.isTemplateApplied;
            }
        }
        #endregion

        #region Constructor
        public NControl()
        {
            base.Loaded += OnLoaded;
            base.Unloaded += OnUnloaded;
            this.currentVisualState = string.Empty;
            base.SetBinding(InnerDataContextProperty, new Binding());
        }
        #endregion

        #region ApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.isTemplateApplied = true;
        }
        #endregion

        #region DependencyProperties
        public static DependencyProperty IsFocusedProperty =
            DependencyProperty.Register("IsFocused", typeof(bool), typeof(NControl), new PropertyMetadata(false, OnIsFocusedChanged));

        public static DependencyProperty InnerDataContextProperty =
            DependencyProperty.Register("InnerDataContext", typeof(object), typeof(NControl), new PropertyMetadata(OnDataContextChanged));

        private static void OnIsFocusedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            NControl nControl = (NControl)sender;
            nControl.isFocused = (bool)args.NewValue;
            //nControl.UpdateVisualState(nControl.isLoaded);
        }

        private static void OnDataContextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            NControl nControl = (NControl)sender;
            nControl.OnDataContextChanged();
        }

        protected virtual void OnDataContextChanged()
        {

        }
        #endregion

        #region Method
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            this.IsFocused = true;
        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            base.OnLostFocus(e);
            this.IsFocused = false;
        }

        protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
        {
            this.isLoaded = false;
        }

        protected virtual void OnLoaded(object sender, RoutedEventArgs e)
        {
            this.isLoaded = true;
            this.IsFocused = true;
        }
        
        protected internal void UpdateVisualState(bool animate)
        {
            if (!this.CanUpdateVisualState())
            {
                return;
            }
            //计算状态名称
            string stateName = this.ComposeVisualStateName();
            if (stateName != this.currentVisualState)
            {
                this.currentVisualState = stateName;
                this.SetVisualState(stateName, animate);
            }
        }
        /// <summary>
        /// 改变控件状态
        /// </summary>
        /// <param name="stateName"></param>
        /// <param name="animate"></param>
        protected virtual void SetVisualState(string stateName, bool animate)
        {
            string[] array = stateName.Split(VisualStateDelimiter);
            for (int i = 0; i < array.Length; i++)
            {
                string name = array[i];
                VisualStateManager.GoToState(this, name, animate);
            }
        }

        /// <summary>
        /// 测算State名称
        /// </summary>
        /// <returns></returns>
        protected virtual string ComposeVisualStateName()
        {
            return string.Empty;
        }

        /// <summary>
        /// 当模版填充并且stateLock == 0 时才可以更新状态
        /// </summary>
        /// <returns></returns>
        protected virtual bool CanUpdateVisualState()
        {
            return this.isTemplateApplied && this.visualStateUpdateLock == 0;
        }

        protected internal void BeginVisualStateUpdate()
        {
            this.visualStateUpdateLock += 1;
        }

        protected internal void EndVisualStateUpdate(bool update,bool animate)
        {
            if (this.visualStateUpdateLock > 0)
            {
                this.visualStateUpdateLock -= 1;
            }
            if (update && this.visualStateUpdateLock == 0)
            {
                this.UpdateVisualState(animate);
            }
        }
        #endregion
    }
}
